/*
   Copyright (c) [Year] [name of copyright holder]
   [Software Name] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.  
*/

#ifndef JIAJIA_LMCC_REDUCESTACK_HPP
#define JIAJIA_LMCC_REDUCESTACK_HPP

#include"jiajiastd.hpp"
#include"jjtoken.hpp"

namespace jiajia{
    namespace lmcc{
        struct rsnode{
            word_t word;
            jiajia::jjtoken token;
            jiajia::jjirnode * begin;
            jiajia::jjirnode * end;
            jiajia::value_t * result;

            rsnode(word_t w):
                word(w),
                token(),
                begin(nullptr),
                end(nullptr),
                result(nullptr)
                {}

            rsnode(const jiajia::jjtoken & t):
                word(t.word),
                token(t),
                begin(nullptr),
                end(nullptr),
                result(nullptr)
                {}

            rsnode(jiajia::jjtoken && t):
                word(t.word),
                token(std::move(t)),
                begin(nullptr),
                end(nullptr),
                result(nullptr)
                {}

            rsnode(word_t w, const jiajia::jjtoken & t, jiajia::jjirnode * b, jiajia::jjirnode * e, jiajia::value_t * r):
                word(w),
                token(t),
                begin(b),
                end(e),
                result(r)
                {}

            rsnode(word_t w, jiajia::jjtoken && t, jiajia::jjirnode * b, jiajia::jjirnode * e, jiajia::value_t * r):
                word(w),
                token(std::move(t)),
                begin(b),
                end(e),
                result(r)
                {}

            rsnode(word_t w, jiajia::jjirnode * b, jiajia::jjirnode * e):
                word(w),
                token(),
                begin(b),
                end(e),
                result(nullptr)
                {}

            rsnode(word_t w, jiajia::value_t * r):
                word(w),
                token(),
                begin(nullptr),
                end(nullptr),
                result(r)
                {}

            rsnode(const rsnode & node):
                word(node.word),
                token(node.token),
                begin(node.begin),
                end(node.end),
                result(node.result)
                {}

            rsnode(rsnode && node):
                word(node.word),
                token(std::move(node.token)),
                begin(node.begin),
                end(node.end),
                result(node.result)
                {
                    node.word = _empty;
                    node.begin = nullptr;
                    node.end = nullptr;
                    node.result = nullptr;
                }

            rsnode & operator=(rsnode && e){
                word = e.word;
                token = std::move(e.token);
                begin = e.begin;
                end = e.end;
                result = e.result;
                return *this;
            }

            rsnode & operator=(const rsnode & e){
                word = e.word;
                token = e.token;
                begin = e.begin;
                end = e.end;
                result = e.result;
                return *this;
            }

            void set(const word_t w){
                word = w;
            }

            void set(const word_t w, jiajia::value_t * r){
                word = w;
                result = r;
            }

            void set(const word_t w, jiajia::jjirnode * b, jiajia::jjirnode * e){
                word = w;
                begin = b;
                end = e;
            }

            void set(const word_t w, jiajia::jjirnode * b, jiajia::jjirnode * e, jiajia::value_t * r){
                word = w;
                begin = b;
                end = e;
                result = r;
            }

            void set(const word_t w, jiajia::jjtoken && t, jiajia::jjirnode * b, jiajia::jjirnode * e, jiajia::value_t * r){
                word = w;
                token = std::move(t);
                begin = b;
                end = e;
                result = r;
            }
        };

        // 该类是用于 lmcc 所生成的解析函数用的存储栈
        class reducestack{
        private:
            std::deque<rsnode> mStack;

            reducestack():mStack(){}
        public:

            static reducestack & en(){
                static reducestack s;
                return s;
            }

            void push(const rsnode & node){
                mStack.push_back(node);
            }

            void push(rsnode && node){
                mStack.push_back(std::move(node));
            }

            void pushToken(jiajia::jjtoken && t){
                mStack.push_back(std::move(rsnode(std::move(t))));
            }

            void pushToken(const word_t w, jiajia::jjtoken && t){
                mStack.push_back(std::move(rsnode(std::move(t))));
                mStack.back().word = w;
            }

            void pushToken(const word_t w, const jiajia::jjtoken & t){
                mStack.push_back(std::move(rsnode(t)));
                mStack.back().word = w;
            }

            void pushToken(const jiajia::jjtoken & t){
                mStack.push_back(std::move(rsnode(t)));
            }

            void pushWord(const word_t w){
                mStack.push_back(std::move(rsnode(w)));
            }

            void pushExpr(const word_t w, const jiajia::jjtoken & t, jiajia::jjirnode * begin, jiajia::jjirnode * end, jiajia::value_t * result){
                mStack.push_back(std::move(rsnode(w, t, begin, end, result)));
            }

            void pushExpr(const word_t w, jiajia::jjtoken && t, jiajia::jjirnode * begin, jiajia::jjirnode * end, jiajia::value_t * result){
                mStack.push_back(std::move(rsnode(w, std::move(t), begin, end, result)));
            }

            void pushResult(const word_t w, value_t * result){
                mStack.push_back(std::move(rsnode(w, result)));
            }

            void pushStmt(const word_t w, jiajia::jjirnode * begin, jiajia::jjirnode * end){
                mStack.push_back(std::move(rsnode(w, begin, end)));
            }

            inline rsnode & top(){
                return mStack.back();
            }

            inline word_t topWord(){
                return mStack.back().word;
            }

            inline jiajia::value_t * topResult(){
                return mStack.back().result;
            }

            inline jiajia::jjtoken & topToken(){
                return mStack.back().token;
            }

            inline rsnode & topExpr(){
                return mStack.back();
            }

            inline void pop(){
                mStack.pop_back();
            }

            inline bool empty(){
                return mStack.empty();
            }

            inline void clear(){
                mStack.clear();
            }
        };
    }
}

#endif
